/**
 * Project name : sklay-core File name : JpaAuthorizingRealm.java Package name :
 * com.sklay.core.web Date : 2013-11-27 Copyright : 2013 , sklay.COM All Rights
 * Reserved Author : 1988fuyu@163.com
 */
package com.hoperun.shiro;

import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.google.common.collect.Sets;
import com.hoperun.bean.AdminManager;
import com.hoperun.bean.AdminManagerRoles;
import com.hoperun.bean.AdminRoles;
import com.hoperun.framework.query.Criteria;
import com.hoperun.framework.util.Constant;
import com.hoperun.service.IAdminManagerRolesSV;
import com.hoperun.service.IAdminManagerSV;

/**
 * .
 * <p/>
 * 
 * @author <a href="mailto:1988fuyu@163.com">1988fuyu</a>
 * @version V1.0, 2012-12-12
 * @param <T>
 */
public class XHZRealm extends AuthorizingRealm {

	@Resource
	private IAdminManagerSV adminManagerSV;

	@Resource
	private IAdminManagerRolesSV adminManagerRolesSV;

	public XHZRealm() {
		super.setAuthenticationCachingEnabled(false);
		// 授权
		super.setAuthorizationCacheName(Constant.AUTHORIZATION_CACHE_NAME);
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		if (principals == null) {
			throw new AuthorizationException(
					"PrincipalCollection method argument cannot be null.");
		}
		AdminManager adminManager = (AdminManager) getAvailablePrincipal(principals);
		// Criteria criteria = new Criteria();
		// criteria.addEqual(MallUser.COL_ID, userId);
		// MallUser user = getEntity(criteria);

		if (adminManager == null) {
			return null;
		} else {
			Long managerId = adminManager.getManagerId();
			Set<String> rolesSet = Sets.newHashSet();
			Set<String> perms = Sets.newHashSet();
			List<AdminManagerRoles> roles = getRoles(managerId);

			if (CollectionUtils.isNotEmpty(roles)) {
				for (AdminManagerRoles adminManagerRole : roles) {
					AdminRoles adminRoles = adminManagerRole.getAdminRoles();
					if (adminRoles != null) {
						rolesSet.add("" + adminRoles.getRoleId());
						String roleStr = adminRoles.getPermissions();
						if (StringUtils.isNotBlank(roleStr)) {
							perms.addAll(Sets.newHashSet(roleStr.split(",")));
						}
					}
				}
			}

			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

			info.setRoles(rolesSet);
			info.setStringPermissions(perms);
			return info;
		}
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {

		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		String username = upToken.getUsername();

		// Null username is invalid
		if (username == null) {
			throw new AccountException(
					"Null usernames are not allowed by this realm.");
		}
		Criteria criteria = new Criteria();
		criteria.addEqual(AdminManager.COL_ACCOUT, username, Criteria.AND);
		AdminManager user = getEntity(criteria);

		if (user == null) {
			throw new UnknownAccountException();
		}

		SimpleAuthenticationInfo info = null;
		String password = user.getPassword();
		if (password == null) {
			throw new UnknownAccountException("No account found for user ["
					+ username + "]");
		}

		info = new SimpleAuthenticationInfo(user, password.toCharArray(),
				getName());

		return info;
	}

	private AdminManager getEntity(Criteria criteria) {

		List<AdminManager> results;
		try {
			results = adminManagerSV.queryByCondition(criteria);
			if (CollectionUtils.isNotEmpty(results)) {
				return results.get(0);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private List<AdminManagerRoles> getRoles(Long managerId) {

		List<AdminManagerRoles> results;
		try {

			Criteria criteria = new Criteria();
			criteria.addEqual(AdminManagerRoles.COL_MANAGER_ID, managerId,
					Criteria.AND);

			results = adminManagerRolesSV.queryBySpecificCondition(criteria);
			if (CollectionUtils.isNotEmpty(results)) {
				return results;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}
